home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 3: Developer Tools
/
Linux Cubed Series 3 - Developer Tools.iso
/
devel
/
lang
/
lisp
/
guile-ii.src
/
guile-ii
/
guile-src
/
guile-docs
/
user
/
scm.info-4
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
GNU Info File
|
1995-06-08
|
48.8 KB
|
1,408 lines
This is Info file scm.info, produced by Makeinfo-1.55 from the input
file scm.texi.
File: scm.info, Node: Gwish, Next: System Calls, Prev: Tk Facilities, Up: Guile Facilities
Gwish
=====
Gwish is a Wish-like application of Guile, based on STk by Erick
Gallesio.
Running Gwish
-------------
Mapping Tcl/Tk Constructs onto Gwish
------------------------------------
In Gwish, there is a single Tcl/Tk interpreter which is an implicit
default. Commands defined in that interpreter are automaticly defined
as Scheme commands as well (unless a Scheme-specific binding overwrites
them). This means that you can write Scheme code that closely matches
the corresponding Tcl code. For example:
(button '.b)
(.b 'configure :text "hello world" :command (tcl-lambda () (beep)))
Arguments passed to a procedure implemented by a Tcl command must be
converted to a string for the sake of Tcl's calling conventions and data
representations. This table illustrates how argument types are
converted:
;;----------------------------------------
;; Argument Converted argument
;;----------------------------------------
123 "123"
123.34 "123.34"
"a-string" "a-string"
'a-symbol "a-symbol"
:keyword "-keyword"
#t "1"
#f "0"
(lambda (...) ...) "*__guile#234"
Most of these conversions are simple and obvious but the conversion of
procedure objects is subtle and non-obvious. It is not necessary to
understand the details, though they are documented elsewhere. It is
necessary to know that procedure arguments `do the right thing' when
they are passed as command parameters to widget configuration commands,
and as event bindings. You might ask: what is the right thing?
A procedure passed as either an event binding or widget command is
protected by the binding or widget involved. Effectively, the widget
or binding keeps a reference to the procedure object. For this reason,
it is possible to use an anonymous Scheme procedure as an event binding
or widget command. For example:
(let ((n 0))
(.b configure :command (lambda ()
(write n)
(newline)
(set! n + 1)
"")))
;; Incidently, note that the command procedure returns an empty string.
;; All procedures called by Tcl have to return a proper Tcl result.
;; Return values are explained further in the next subsection.
;;
When a command or binding is overwritten and that command or binding
is to a Scheme procedure, the reference to the procedure is dropped.
The procedure is also dropped if the binding or widget is deleted. For
this reason, there are no core leaks associated with passing anonymous
procedures as these kinds of arguments.
At this time, it isn't generally useful to pass Scheme procedures to
Tcl commands other than as an argument to a binding command or widget
configuration command.
The details of how procedures are translated are described in the
documentation for `tcl-apply-command'. *Note Tcl Facilities::.
Defining Tcl Command in Scheme
------------------------------
Gwish provides a convenient syntax for defining new Tcl commands.
- Syntax: proc NAME FORMALS . BODY
Define a new Tcl command and Scheme procedure simultaneously.
;; A two argument string-append callable as a Tcl command.
;;
(proc string-smash (s1 s2) (string-append s1 s2))
Proc expands to a `tcl-lambda' form, which is explained below.
The example above is equivalent to:
(begin
(define string-smash (tcl-lambda (s1 s2) (string-append s1 s2)))
(tcl-create-command the-interpreter 'string-smash string-smash))
- Syntax: tcl-lambda (?CALLING-CONVENTION? ?.? FORMALS) . BODY
Similar to lambda, but imposes Tcl-specific calling conventions.
Type declarations are supported. This is best explained via
examples.
A simple use of `tcl-lambda':
;; By default, when called from Tcl, all of the arguments
;; to a tcl-lambda are strings.
;;
(tcl-lambda (a b) (string-append a b))
The return value of a tcl-lambda has special signficance when the
function is invoked by Tcl.
An integer return value is converted to a string. A string or
symbol is used used directly as a Tcl result. A cons pair with an
integer car and string cdr is a Tcl status/message combination.
Type declarations can be used to specify that parameters passed as
strings should be coerced to some other type. For example:
(define tcl-plus
(tcl-lambda ((number a) (number b))
(+ a b)))
(tcl-plus "23" 19) => 42
Tcl-lambda is very useful for using anonymous Scheme functions as
Tk event bindings. For this purpose, you can can specify a Tk
"calling convention" by writing a string in the first of the
argument specification. For example:
(.c 'bind 'node "<Button-2>"
(tcl-lambda ("%x %y" (number x) (number y))
(set! cur-x x)
(set! cur-y y)
#t)) ; Tcl-compatible return value.
In that example, `"%x %y"' is the calling convention. The full
command that Tcl calls when invoking the binding will be similar
to:
__binding#0x123123 %x %y
and therefore the Scheme procedure will be passed (in this case)
the x and y position of the mouse.
An Example: Ousterhout's Graph Editor
-------------------------------------
This program implements the toy graph editor from the Tcl/Tk <fixme>.
File: scm.info, Node: System Calls, Next: Gscsh, Prev: Gwish, Up: Guile Facilities
System Calls
============
A volunteer is need to write this section. Most of the system call
documentation already exists in other sections. See also *Note
I/O-Extensions::, *Note Posix Extensions::.
All of the unix system calls are available as Scheme procedures.
Any call that fails with errno EINTR is automaticly retried.
By default, any other error during a system call will cause the call
to signal an error and not return. There are two functions that control
this behavior and which you can redefine. These are `syscall' and
`syserror'. The default definitions are:
(define (syserror key fn err . args)
(errno err)
(apply error (cons fn args)))
(define (syscall thunk)
(errno 0)
(catch 'syserror thunk syserror))
A typical system call is written this way:
(define (connect port address . args)
(syscall
(lambda ()
(let ((rv (apply %connect (cons port (cons address args)))))
(if (eq? rv #f)
(throw 'syserror 'connect (errno) port address args))))))
File: scm.info, Node: Gscsh, Prev: System Calls, Up: Guile Facilities
Gscsh
=====
- Function: fork
- Function: fork THUNK
Fork a child process: returns child pid to parent, #f to child.
With an argument, fork a child process executing the Scheme
procedure thunk. Returns child pid to parent.
- Function: wait
- Function: wait PID
- Function: wait PID OPTIONS
Wait for any child to terminate.
Pid argument means for that child process to terminate. Special
values for pid are: -1 wait for any child process; 0 wait for any
child process in the process group of the calling process.
Options is an integer with the following OR'd values:
WNOHANG: do not wait.
WUNTRACED: also return status information from stopped processes.
- Function: exec-pipe PIPE
- Function: fg-pipe PIPE
- Function: bg-pipe PIPE
These functions run external programs in a pipeline. exec-pipe
causes the pipeline to overlay the current process. fg-pipe waits
for the first command in the pipeline to exit and returns its exit
status code. bg-pipe runs the pipeline in the background,
returning a list with the process id of the first program and
ports which can be used for communicating with the programs in the
pipeline.
The pipe argument consists of a series of commands and optionally
connection lists. A command can be either an external Unix
program or a scheme procedure. An external program is written as
a list of strings with the name and arguments. An example of a
pipeline connecting three programs and using the default
connection lists is:
(exec-pipe
'("cat" "/etc/passwd") '("sort" "-t:" "+2") '("grep" "^u"))
Alternatively a Scheme procedure (taking no arguments) may be
specified and will be run in its own subprocess. The standard
ports (current-input-port, current-output-port and
current-error-port) are created automatically from file
descriptors 0, 1 and 2. A Scheme procedure used in a pipeline
would typically be a filter, such as:
(define filter
(lambda ()
(let loop ((ch (read-char)))
(cond ((not (eof-object? ch))
(display ch)
(loop (read-char)))))))
and the term in the pipeline would be written:
`(,filter)
A connection list specifies how open Scheme ports are connected to
Unix file descriptors in the programs in the pipeline and how file
descriptors are wired together between programs. For example, the
default connection list between the sort and grep commands in the
pipeline above is:
`((1 0) (2 ,(current-error-port)))
which says to connect file descriptor 1 (standard output) from the
sort command to file descriptor 0 (standard input) in the grep
command and to connect file descriptor 2 (standard error) from the
sort command to the Scheme current error port.
Connection lists may be placed between programs in the pipeline
and if omitted the default above will be used. Connection lists
may also be placed before the first program and after the last to
specify connections at the beginning and end of the pipeline. The
default connection list then depends on which pipeline function is
used.
The defaults for exec-pipe and fg-pipe are:
`((,(current-input-port) 0))
`((1 ,(current-output-port)) (2 ,(current-error-port)))
for the input and output ends of the pipeline respectively.
The defaults for bg-pipe are:
'((return-port 0))
`((1 return-port) (2 ,(current-error-port)))
The symbol 'return-port in the connection list adds a port to the
list returned by bg-pipe. In the default case two ports are
returned: the first is an output port connected to the standard
input of the first program in the pipeline and the second is an
input port connected to the standard output of the last process.
[need to beware of deadlocks if multiple output ports are
returned].
The pipeline example above can be rewritten with all the
connection lists given explicitly:
(exec-pipe `((,(current-input-port) 0))
'("cat" "/etc/passwd") `((1 0) (2 ,(current-error-port)))
'("sort" "-t:" "+2") `((1 0) (2 ,(current-error-port)))
'("grep" "^u") `((1 ,(current-output-port)) (2 ,(current-error-port)))
Multiple file descriptors can be connected to a single target if a
connection list such as '((1 0) (2 0)) or equivalently '((1 2 0))
is specified.
A final construction which can be used in a connection list is a
string to be interpreted as the name of a file. For example, the
connection list between the sort and grep commands could be
written:
'((1 0) (2 "sort-errors"))
which would capture the standard error from sort to a newly
created file. [Maybe this should be extended to allow appending
to a file, e.g., with ">sort-error-log", although it could also be
done with ports].
File: scm.info, Node: Internals, Next: Procedure and Macro Index, Prev: Guile Facilities, Up: Top
Internals
*********
* Menu:
* Data Types::
* Operations::
* Improvements To Make::
* Finishing Dynamic Linking::
File: scm.info, Node: Data Types, Next: Operations, Prev: Internals, Up: Internals
Data Types
==========
In the descriptions below it is assumed that `long int's are 32 bits in
length. Acutally, SCM is written to work with any `long int' size
larger than 31 bits. With some modification, SCM could work with word
sizes as small as 24 bits.
All SCM objects are represented by type "SCM". Type `SCM' come in 2
basic flavors, Immediates and Cells:
* Menu:
* Immediates::
* Cells::
* Data Type Representations::
File: scm.info, Node: Immediates, Next: Cells, Prev: Data Types, Up: Data Types
Immediates
----------
An "immediate" is a data type contained in type `SCM' (`long int').
The type codes distinguishing immediate types from each other vary in
length, but reside in the low order bits.
- Macro: IMP X
- Macro: NIMP X
Return non-zero if the `SCM' object X is an immediate or
non-immediate type, respectively.
- Immediate: inum
immediate 30 bit signed integer. An INUM is flagged by a `1' in
the second to low order bit position. The high order 30 bits are
used for the integer's value.
- Macro: INUMP X
- Macro: NINUMP X
Return non-zero if the `SCM' X is an immediate integer or not
an immediate integer, respectively.
- Macro: INUM X
Returns the C `long integer' corresponding to `SCM' X.
- Macro: MAKINUM X
Returns the `SCM' inum corresponding to C `long integer' x.
- Immediate Constant: INUM0
is equivalent to `MAKINUM(0)'.
Computations on INUMs are performed by converting the arguments to
C integers (by a shift), operating on the integers, and converting
the result to an inum. The result is checked for overflow by
converting back to integer and checking the reverse operation.
The shifts used for conversion need to be signed shifts. If the C
implementation does not support signed right shift this fact is
detected in a #if statement in `scmfig.h' and a signed right shift,
`SRS', is constructed in terms of unsigned right shift.
- Immediate: ichr
characters.
- Macro: ICHRP X
Return non-zero if the `SCM' object X is a character.
- Macro: ICHR X
Returns corresponding `unsigned char'.
- Macro: MAKICHR X
Given `char' X, returns `SCM' character.
- Immediate: iflags
These are frequently used immediate constants.
- Immediate Constant: SCM BOOL_T
`#t'
- Immediate Constant: SCM BOOL_F
`#f'
- Immediate Constant: SCM EOL
`()'. If `SICP' is `#define'd, `EOL' is `#define'd to be
identical with `BOOL_F'. In this case, both print as `#f'.
- Immediate Constant: SCM EOF_VAL
end of file token, `#<eof>'.
- Immediate Constant: SCM UNDEFINED
`#<undefined>' used for variables which have not been defined
and absent optional arguments.
- Immediate Constant: SCM UNSPECIFIED
`#<unspecified>' is returned for those procedures whose return
values are not specified.
- Macro: IFLAGP N
Returns non-zero if N is an ispcsym, isym or iflag.
- Macro: ISYMP N
Returns non-zero if N is an ispcsym or isym.
- Macro: ISYMNUM N
Given ispcsym, isym, or iflag N, returns its index in the C array
`isymnames[]'.
- Macro: ISYMCHARS N
Given ispcsym, isym, or iflag N, returns its `char *'
representation (from `isymnames[]').
- Macro: MAKSPCSYM N
Returns `SCM' ispcsym N.
- Macro: MAKISYM N
Returns `SCM' iisym N.
- Macro: MAKIFLAG N
Returns `SCM' iflag N.
- Variable: isymnames
An array of strings containing the external representations of all
the ispcsym, isym, and iflag immediates. Defined in `repl.c'.
- Constant: NUM_ISPCSYM
- Constant: NUM_ISYMS
The number of ispcsyms and ispcsyms+isyms, respectively. Defined
in `scm.h'.
- Immediate: isym
`and', `begin', `case', `cond', `define', `do', `if', `lambda',
`let', `let*', `letrec', `or', `quote', `set!', `#f', `#t',
`#<undefined>', `#<eof>', `()', and `#<unspecified>'.
- CAR Immediate: ispcsym
special symbols: syntax-checked versions of first 14 isyms
- CAR Immediate: iloc
indexes to a variable's location in environment
- CAR Immediate: gloc
pointer to a symbol's value cell
- Immediate: CELLPTR
pointer to a cell (not really an immediate type, but here for
completeness). Since cells are always 8 byte aligned, a pointer
to a cell has the low order 3 bits `0'.
There is one exception to this rule, *CAR Immediate*s, described
next.
A "CAR Immediate" is an Immediate point which can only occur in the
`CAR's of evaluated code (as a result of `ceval''s memoization process).
File: scm.info, Node: Cells, Next: Data Type Representations, Prev: Immediates, Up: Data Types
Cells
-----
"Cell"s represent all SCM objects other than immediates. A cell has a
`CAR' and a `CDR'. Low-order bits in `CAR' identify the type of
object. The rest of `CAR' and `CDR' hold object data. The number
after `tc' specifies how many bits are in the type code. For instance,
`tc7' indicates that the type code is 7 bits.
- Macro: NEWCELL X
Allocates a new cell and stores a pointer to it in `SCM' local
variable X.
Care needs to be taken that stores into the new cell pointed to by
X do not create an inconsistent object. *Note Signals::.
All of the C macros decribed in this section assume that their argument
is of type `SCM' and points to a cell (`CELLPTR').
- Macro: CAR X
- Macro: CDR X
Returns the `car' and `cdr' of cell X, respectively.
- Macro: TYP3 X
- Macro: TYP7 X
- Macro: TYP16 X
Returns the 3, 7, and 16 bit type code of a cell.
- Cell: tc3_cons
scheme cons-cell returned by (cons arg1 arg2).
- Macro: CONSP X
- Macro: NCONSP X
Returns non-zero if X is a `tc3_cons' or isn't, respectively.
- Cell: tc3_closure
applicable object returned by (lambda (args) ...). `tc3_closure's
have a pointer to other the body of the procedure in the `CAR' and
a pointer to the environment in the `CDR'.
- Macro: CLOSUREP X
Returns non-zero if X is a `tc3_closure'.
- Macro: CODE X
- Macro: ENV X
Returns the code body or environment of closure X,
respectively.
"Header"s are Cells whose `CDR's point elsewhere in memory, such as to
memory allocated by `malloc'.
- Header: spare
spare `tc7' type code
- Header: tc7_vector
scheme vector.
- Macro: VECTORP X
- Macro: NVECTORP X
Returns non-zero if X is a `tc7_vector' or if not,
respectively.
- Macro: VELTS X
- Macro: LENGTH X
Returns the C array of `SCM's holding the elements of vector
X or its length, respectively.
- Header: tc7_ssymbol
static scheme symbol (part of initial system)
- Header: tc7_msymbol
`malloc'ed scheme symbol (can be GCed)
- Macro: SYMBOLP X
Returns non-zero if X is a `tc7_ssymbol' or `tc7_msymbol'.
- Macro: CHARS X
- Macro: UCHARS X
- Macro: LENGTH X
Returns the C array of `char's or as `unsigned char's holding
the elements of symbol X or its length, respectively.
- Header: tc7_string
scheme string
- Macro: STRINGP X
- Macro: NSTRINGP X
Returns non-zero if X is a `tc7_string' or isn't,
respectively.
- Macro: CHARS X
- Macro: UCHARS X
- Macro: LENGTH X
Returns the C array of `char's or as `unsigned char's holding
the elements of string X or its length, respectively.
- Header: tc7_bvect
uniform vector of booleans (bit-vector)
- Header: tc7_ivect
uniform vector of integers
- Header: tc7_uvect
uniform vector of non-negative integers
- Header: tc7_fvect
uniform vector of short inexact real numbers
- Header: tc7_dvect
uniform vector of double precision inexact real numbers
- Header: tc7_cvect
uniform vector of double precision inexact complex numbers
- Header: tc7_contin
applicable object produced by call-with-current-continuation
- Header: tc7_cclo
Subr and environment for compiled closure
A cclo is similar to a vector (and is GCed like one), but can be
applied as a function:
1. the cclo itself is consed onto the head of the argument list
2. the first element of the cclo is applied to that list. Cclo
invocation is currently not tail recursive when given 2 or
more arguments.
- Function: makcclo PROC LEN
makes a closure from the *subr* PROC with LEN-1 extra
locations for `SCM' data. Elements of a CCLO are referenced
using `VELTS(cclo)[n]' just as for vectors.
A "Subr" is a header whose `CDR' points to a C code procedure. Scheme
primitive procedures are subrs. Except for the arithmetic `tc7_cxr's,
the C code procedures will be passed arguments (and return results) of
type `SCM'.
- Subr: tc7_asubr
associative C function of 2 arguments. Examples are `+', `-',
`*', `/', `max', and `min'.
- Subr: tc7_subr_0
C function of no arguments.
- Subr: tc7_subr_1
C function of one argument.
- Subr: tc7_cxr
These subrs are handled specially. If inexact numbers are
enabled, the `CDR' should be a function which takes and returns
type `double'. Conversions are handled in the interpreter.
`floor', `ceiling', `truncate', `round', `$sqrt', `$abs', `$exp',
`$log', `$sin', `$cos', `$tan', `$asin', `$acos', `$atan',
`$sinh', `$cosh', `$tanh', `$asinh', `$acosh', `$atanh', and
`exact->inexact' are defined this way.
If the `CDR' is `0' (`NULL'), the name string of the procedure is
used to control traversal of its list structure argument.
`car', `cdr', `caar', `cadr', `cdar', `cddr', `caaar', `caadr',
`cadar', `caddr', `cdaar', `cdadr', `cddar', `cdddr', `caaaar',
`caaadr', `caadar', `caaddr', `cadaar', `cadadr', `caddar',
`cadddr', `cdaaar', `cdaadr', `cdadar', `cdaddr', `cddaar',
`cddadr', `cdddar', and `cddddr' are defined this way.
- Subr: tc7_subr_3
C function of 3 arguments.
- Subr: tc7_subr_2
C function of 2 arguments.
- Subr: tc7_rpsubr
transitive relational predicate C function of 2 arguments. The C
function should return either `BOOL_T' or `BOOL_F'.
- Subr: tc7_subr_1o
C function of one optional argument. If the optional argument is
not present, `UNDEFINED' is passed in its place.
- Subr: tc7_subr_2o
C function of 1 required and 1 optional argument. If the optional
argument is not present, `UNDEFINED' is passed in its place.
- Subr: tc7_lsubr_2
C function of 2 arguments and a list of (rest of) `SCM' arguments.
- Subr: tc7_lsubr
C function of list of `SCM' arguments.
A "ptob" is a port object, capable of delivering or accepting
characters. *Note Ports: (r4rs)Ports. Unlike the types described so
far, new varieties of ptobs can be defined dynamically (*note Defining
Ptobs::.). These are the initial ptobs:
- ptob: tc16_inport
input port.
- ptob: tc16_outport
output port.
- ptob: tc16_ioport
input-output port.
- ptob: tc16_inpipe
input pipe created by `popen()'.
- ptob: tc16_outpipe
output pipe created by `popen()'.
- ptob: tc16_strport
String port created by `cwos()' or `cwis()'.
- ptob: tc16_sfport
Software (virtual) port created by `mksfpt()' (*note Soft
Ports::.).
- Macro: PORTP X
- Macro: OPPORTP X
- Macro: OPINPORTP X
- Macro: OPOUTPORTP X
- Macro: INPORTP X
- Macro: OUTPORTP X
Returns non-zero if X is a port, open port, open input-port, open
output-port, input-port, or output-port, respectively.
- Macro: OPENP X
- Macro: CLOSEDP X
Returns non-zero if port X is open or closed, respectively.
- Macro: STREAM X
Returns the `FILE *' stream for port X.
Ports which are particularly well behaved are called "fport"s.
Advanced operations like `file-position' and `reopen-file' only work
for fports.
- Macro: FPORTP X
- Macro: OPFPORTP X
- Macro: OPINFPORTP X
- Macro: OPOUTFPORTP X
Returns non-zero if X is a port, open port, open input-port, or
open output-port, respectively.
A "smob" is a miscellaneous datatype. The type code and GCMARK bit
occupy the lower order 16 bits of the `CAR' half of the cell. The rest
of the `CAR' can be used for sub-type or other information. The `CDR'
contains data of size long and is often a pointer to allocated memory.
Like ptobs, new varieties of smobs can be defined dynamically (*note
Defining Smobs::.). These are the initial smobs:
- smob: tc_free_cell
unused cell on the freelist.
- smob: tc16_flo
single-precision float.
Inexact number data types are subtypes of type `tc16_flo'. If the
sub-type is:
0. a single precision float is contained in the `CDR'.
1. `CDR' is a pointer to a `malloc'ed double.
3. `CDR' is a pointer to a `malloc'ed pair of doubles.
- smob: tc_dblr
double-precision float.
- smob: tc_dblc
double-precision complex.
- smob: tc16_bigpos
- smob: tc16_bigneg
positive and negative bignums, respectively.
Scm has large precision integers called bignums. They are stored
in sign-magnitude form with the sign occuring in the type code of
the SMOBs bigpos and bigneg. The magnitude is stored as a
`malloc'ed array of type `BIGDIG' which must be an unsigned
integral type with size smaller than `long'. `BIGRAD' is the
radix associated with `BIGDIG'.
- smob: tc16_promise
made by DELAY. *Note Control features: (r4rs)Control features.
- smob: tc16_arbiter
synchronization object. *Note Process Synchronization::.
- smob: tc16_macro
macro expanding function. *Note Low Level Syntactic Hooks::.
- smob: tc16_array
multi-dimensional array. *Note Arrays::.
This type implements both conventional arrays (those with
arbitrary data as elements *note Conventional Arrays::.) and
uniform arrays (those with elements of a uniform type *note
Uniform Array::.).
Conventional Arrays have a pointer to a vector for their `CDR'.
Uniform Arrays have a pointer to a Uniform Vector type (string,
bvect, ivect, uvect, fvect, dvect, or cvect) in their `CDR'.
File: scm.info, Node: Data Type Representations, Prev: Cells, Up: Data Types
Data Type Representations
-------------------------
IMMEDIATE: B,D,E,F=data bit, C=flag code, P=pointer address bit
................................
inum BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB10
ichr BBBBBBBBBBBBBBBBBBBBBBBB11110100
iflag CCCCCCC101110100
isym CCCCCCC001110100
IMCAR: only in car of evaluated code, cdr has cell's GC bit
ispcsym 000CCCC00CCCC100
iloc 0DDDDDDDDDDDDDDDEFFFFFFF11111100
pointer PPPPPPPPPPPPPPPPPPPPPPPPPPPPP000
gloc PPPPPPPPPPPPPPPPPPPPPPPPPPPPP001
HEAP CELL: G=gc_mark; 1 during mark, 0 other times.
1s and 0s here indicate type. G missing means sys (not GC'd)
SIMPLE:
cons ..........SCM car..............0 ...........SCM cdr.............G
closure ..........SCM code...........011 ...........SCM env.............G
HEADERs:
ssymbol .........long length....G0000101 ..........char *chars...........
msymbol .........long length....G0000111 ..........char *chars...........
string .........long length....G0001101 ..........char *chars...........
vector .........long length....G0001111 ...........SCM **elts...........
bvect .........long length....G0010101 ..........long *words...........
spare G0010111
ivect .........long length....G0011101 ..........long *words...........
uvect .........long length....G0011111 ......unsigned long *words......
spare G0100101
spare G0100111
fvect .........long length....G0101101 .........float *words...........
dvect .........long length....G0101111 ........double *words...........
cvect .........long length....G0110101 ........double *words...........
contin .........long length....G0111101 .............*regs..............
cclo .........long length....G0111111 ...........SCM **elts...........
SUBRs:
spare 010001x1
spare 010011x1
subr_0 ..........int hpoff.....01010101 ...........SCM (*f)()...........
subr_1 ..........int hpoff.....01010111 ...........SCM (*f)()...........
cxr ..........int hpoff.....01011101 .........double (*f)()..........
subr_3 ..........int hpoff.....01011111 ...........SCM (*f)()...........
subr_2 ..........int hpoff.....01100101 ...........SCM (*f)()...........
asubr ..........int hpoff.....01100111 ...........SCM (*f)()...........
subr_1o ..........int hpoff.....01101101 ...........SCM (*f)()...........
subr_2o ..........int hpoff.....01101111 ...........SCM (*f)()...........
lsubr_2 ..........int hpoff.....01110101 ...........SCM (*f)()...........
lsubr_2n..........int hpoff.....01110111 ...........SCM (*f)()...........
rpsubr ..........int hpoff.....01111101 ...........SCM (*f)()...........
PTOBs:
port 0bwroxxxxxxxxG1110111 ..........FILE *stream..........
socket ttttttt 00001xxxxxxxxG1110111 ..........FILE *stream..........
inport uuuuuuuuuuU00011xxxxxxxxG1110111 ..........FILE *stream..........
outport 0000000000000101xxxxxxxxG1110111 ..........FILE *stream..........
ioport uuuuuuuuuuU00111xxxxxxxxG1110111 ..........FILE *stream..........
fport 00 00000000G1110111 ..........FILE *stream..........
pipe 00 00000001G1110111 ..........FILE *stream..........
strport 00 00000010G1110111 ..........FILE *stream..........
sfport 00 00000011G1110111 ..........FILE *stream..........
SMOBs:
free_cell
000000000000000000000000G1111111 ...........*free_cell........000
flo 000000000000000000000001G1111111 ...........float num............
dblr 000000000000000100000001G1111111 ..........double *real..........
dblc 000000000000001100000001G1111111 .........complex *cmpx..........
bignum ...int length...0000001 G1111111 .........short *digits..........
bigpos ...int length...00000010G1111111 .........short *digits..........
bigneg ...int length...00000011G1111111 .........short *digits..........
xxxxxxxx = code assigned by newsmob();
promise 000000000000000fxxxxxxxxG1111111 ...........SCM val..............
arbiter 000000000000000lxxxxxxxxG1111111 ...........SCM name.............
macro 000000000000000mxxxxxxxxG1111111 ...........SCM name.............
array ...short rank..cxxxxxxxxG1111111 ............*array..............
File: scm.info, Node: Operations, Next: Improvements To Make, Prev: Data Types, Up: Internals
Operations
==========
* Menu:
* Garbage Collection:: Automatically reclaims unused storage
* Signals::
* C Macros::
* Changing Scm:: How to *really* screw it up
* Defining Subrs::
* Defining Smobs::
* Defining Ptobs::
* Calling Scheme From C::
* Continuations::
* Evaluation:: Why SCM is fast
File: scm.info, Node: Garbage Collection, Next: Signals, Prev: Operations, Up: Operations
Garbage Collection
------------------
The garbage collector is in the latter half of `sys.c'. Immediates
always appear as parts of other objects, so they are not subject to
explicit garbage collection. There is a heap (composed of heap
segments) in which all cells reside. The storage for strings, vectors,
continuations, doubles, complexes, and bignums is managed by malloc.
There is only one pointer to each malloc object from its type-header
cell in the heap. This allows malloc objects to be freed when the
associated heap object is garbage collected.
To garbage collect, first certain protected objects are marked (such
as symhash). Then the stack (and marked continuations) are traversed.
Each longword in the stack is tried to see if it is a valid cell pointer
into the heap. If it is, the object itself and any objects it points to
are marked. If the stack is word rather than longword aligned
`(#define WORD_ALIGN)', both alignments are tried. This arrangement
will occasionally mark an object which is no longer used. This has not
been a problem in practice and the advantage of using the c-stack far
outweighs it.
The heap is then swept. If a type-header cell pointing to malloc
space is collected the malloc object is then freed. If the type header
of smob is collected, the smob's free procedure is called to free its
storage.
File: scm.info, Node: Signals, Next: C Macros, Prev: Garbage Collection, Up: Operations
Signals
-------
- Function: init_signals
(in `scm.c') initializes handlers for `SIGINT' and `SIGALRM' if
they are supported by the C implementation. All of the signal
handlers immediately reestablish themselves by a call to
`signal()'.
- Function: int_signal SIG
- Function: alrm_signal SIG
The low level handlers for `SIGINT' and `SIGALRM'.
If an interrupt handler is defined when the interrupt is received, the
code is interpreted. If the code returns, execution resumes from where
the interrupt happened. `Call-with-current-continuation' allows the
stack to be saved and restored.
SCM does not use any signal masking system calls. These are not a
portable feature. However, code can run uninterrupted by use of the C
macros `DEFER_INTS' and `ALLOW_INTS'.
- Macro: DEFER_INTS
sets the global variable `ints_disabled' to 1. If an interrupt
occurs during a time when `ints_disabled' is 1 one of the global
variables `sig_deferred' or `alrm_deferred' is set to 1 and the
handler returns.
- Macro: ALLOW_INTS
Checks the deferred variables and if set the appropriate handler is
called.
Calls to `DEFER_INTS' can not be nested. An `ALLOW_INTS' must
happen before another `DEFER_INTS' can be done. In order to check
that this constraint is satisfied `#define CAREFUL_INTS' in
`scmfig.h'.
File: scm.info, Node: C Macros, Next: Changing Scm, Prev: Signals, Up: Operations
C Macros
--------
- Macro: ASSERT COND ARG POS SUBR
signals an error if the expression (COND) is 0. ARG is the
offending object, SUBR is the string naming the subr, and POS
indicates the position or type of error. POS can be one of
* `ARGn' (> 5 or unknown ARG number)
* `ARG1'
* `ARG2'
* `ARG3'
* `ARG4'
* `ARG5'
* `WNA' (wrong number of args)
* `OVFLOW'
* `OUTOFRANGE'
* `NALLOC'
* `EXIT'
* `HUP_SIGNAL'
* `INT_SIGNAL'
* `FPE_SIGNAL'
* `BUS_SIGNAL'
* `SEGV_SIGNAL'
* `ALRM_SIGNAL'
* a C string `(char *)'
Error checking is not done by `ASSERT' if the flag `RECKLESS' is
defined. An error condition can still be signaled in this case
with a call to `wta(arg, pos, subr)'.
- Macro: ASRTGO COND LABEL
`goto' LABEL if the expression (COND) is 0. Like `ASSERT',
`ASRTGO' does is not active if the flag `RECKLESS' is defined.
File: scm.info, Node: Changing Scm, Next: Defining Subrs, Prev: C Macros, Up: Operations
Changing Scm
------------
When writing C-code for SCM, a precaution is recommended. If your
routine allocates a non-cons cell which will *not* be incorporated into
a `SCM' object which is returned, you need to make sure that a `SCM'
variable in your routine points to that cell as long as part of it
might be referenced by your code.
In order to make sure this `SCM' variable does not get optimized out
you can put this assignment after its last possible use:
SCM_dummy1 = foo;
or put this assignment somewhere in your routine:
SCM_dummy1 = (SCM) &foo;
`SCM_dummy' variables are not currently defined. Passing the address
of the local `SCM' variable to *any* procedure also protects it.
Also, if you maintain a static pointer to some (non-immediate) `SCM'
object, you must either make your pointer be the value cell of a symbol
(see `errobj' for an example) or make your pointer be one of the
`sys_protects' (see `symhash' for an example). The former method is
prefered since it does not require any changes to the SCM distribution.
To add a C routine to scm:
1. choose the appropriate subr type from the type list.
2. write the code and put into `scm.c'.
3. add a `make_subr' or `make_gsubr' call to `init_scm'. Or put an
entry into the appropriate `iproc' structure.
To add a package of new procedures to scm (see `crs.c' for example):
1. create a new C file (`foo.c').
2. at the front of `foo.c' put declarations for strings for your
procedure names.
static char s_twiddle_bits[]="twiddle-bits!";
static char s_bitsp[]="bits?";
3. choose the appropriate subr types from the type list in `code.doc'.
4. write the code for the procedures and put into `foo.c'
5. create one `iproc' structure for each subr type used in `foo.c'
static iproc subr3s[]= {
{s_twiddle-bits,twiddle-bits},
{s_bitsp,bitsp},
{0,0} };
6. create an `init_<name of file>' routine at the end of the file
which calls `init_iprocs' with the correct type for each of the
`iproc's created in step 5.
void init_foo()
{
init_iprocs(subr1s, tc7_subr_1);
init_iprocs(subr3s, tc7_subr_3);
}
If your package needs to have a "finalization" routine called to
free up storage, close files, etc, then also have a line in
`init_foo' like:
add_final(final_foo);
`final_foo' should be a (void) procedure of no arguments. The
finals will be called in opposite order from their definition.
The line:
add_feature("foo");
will append a symbol `'foo' to the (list) value of `*features*'.
7. put any scheme code which needs to be run as part of your package
into `Ifoo.scm'.
8. put an `if' into `Init.scm' which loads `Ifoo.scm' if your package
is included:
(if (defined? twiddle-bits!)
(load (in-vicinity (implementation-vicinity)
"Ifoo"
(scheme-file-suffix))))
or use `(provided? 'foo)' instead of `(defined? twiddle-bits!)'
if you have added the feature.
9. put documentation of the new procedures into `foo.doc'
10. add lines to your `Makefile' to compile and link SCM with your
object file. Add a `init_foo\(\)\;' to the `INITS=...' line at
the beginning of the makefile.
These steps should allow your package to be linked into SCM with a
minimum of difficulty. Your package should also work with dynamic
linking if your SCM has this capability.
Special forms (new syntax) can be added to scm.
1. define a new `MAKISYM' in `scm.h' and increment `NUM_ISYMS'.
2. add a string with the new name in the corresponding place in
`isymnames' in `repl.c'.
3. add `case:' clause to `ceval()' near `i_quasiquote' (in `eval.c').
New syntax can now be added without recompiling SCM by the use of the
`procedure->syntax', `procedure->macro', `procedure->memoizing-macro',
and `defmacro'. For details, *Note Syntax Extensions::.
File: scm.info, Node: Defining Subrs, Next: Defining Smobs, Prev: Changing Scm, Up: Operations
Defining Subrs
--------------
If "CCLO" is `#define'd when compiling, the compiled closure feature
will be enabled. It is automatically enabled if dynamic linking is
enabled.
The SCM interpreter directly recognizes subrs taking small numbers of
arguments. In order to create subrs taking larger numbers of arguments
use:
- Function: make_gsubr NAME REQ OPT REST FCN
returns a cclo (compiled closure) object of name `char *' NAME
which takes `int' REQ required arguments, `int' OPT optional
arguments, and a list of rest arguments if `int' REST is 1 (0 for
not).
`SCM (*fcn)()' is a pointer to a C function to do the work.
The C function will always be called with REQ + OPT + REST
arguments, optional arguments not supplied will be passed
`UNDEFINED'. An error will be signaled if the subr is called with
too many or too few arguments. Currently a total of 10 arguments
may be specified, but increasing this limit should not be
difficult.
/* A silly example, taking 2 required args,
1 optional, and a list of rest args */
SCM gsubr_21l(req1,req2,opt,rst)
SCM req1,req2,opt,rst;
{
lputs("gsubr-2-1-l:\n req1: ", cur_outp);
display(req1,cur_outp);
lputs("\n req2: ", cur_outp);
display(req2,cur_outp);
lputs("\n opt: ", cur_outp);
display(opt,cur_outp);
lputs("\n rest: ", cur_outp);
display(rst,cur_outp);
newline(cur_outp);
return UNSPECIFIED;
}
void init_gsubr211()
{
make_gsubr("gsubr-2-1-l", 2, 1, 1, gsubr_21l);
}
File: scm.info, Node: Defining Smobs, Next: Defining Ptobs, Prev: Defining Subrs, Up: Operations
Defining Smobs
--------------
Here is an example of how to add a new type named `foo' to SCM. The
following lines need to be added to your code:
`long tc16_foo;'
The type code which will be used to identify the new type.
`static smobfuns foosmob = {markfoo,freefoo,printfoo,equalpfoo};'
smobfuns is a structure composed of 4 functions:
typedef struct {
SCM (*mark)P((SCM));
sizet (*free)P((CELLPTR));
int (*print)P((SCM exp, SCM port, int writing));
SCM (*equalp)P((SCM, SCM));
} smobfuns;
`smob.mark'
is a function of one argument of type `SCM' (the cell to
mark) and returns type `SCM' which will then be marked. If
no further objects need to be marked then return an immediate
object such as `BOOL_F'. 2 functions are provided:
`markcdr(ptr)'
which marks the current cell and returns `CDR(ptr)'.
`mark0(ptr)'
which marks the current cell and returns `BOOL_F'.
`smob.free'
is a function of one argument of type `CELLPTR' (the cell to
collected) and returns type `sizet' which is the number of
`malloc'ed bytes which were freed. `Smob.free' should free
any `malloc'ed storage associated with this object. The
function free0(ptr) is provided which does not free any
storage and returns 0.
`smob.print'
is 0 or a function of 3 arguments. The first, of type `SCM',
is the smob object. The second, of type `SCM', is the stream
on which to write the result. The third, of type int, is 1
if the object should be `write'n, 0 if it should be
`display'ed. This function should return non-zero if it
printed, and zero otherwise (in which case a hexadecimal
number will be printed).
`smob.equalp'
is 0 or a function of 2 `SCM' arguments. Both of these
arguments will be of type `tc16foo'. This function should
return `BOOL_T' if the smobs are equal, `BOOL_F' if they are
not. If `smob.equalp' is 0, `equal?' will return `BOOL_F' if
they are not `eq?'.
`tc16_foo = newsmob(&foosmob);'
Allocates the new type with the functions from `foosmob'. This
line goes in an `init_' routine.
Promises and macros in `eval.c' and arbiters in `repl.c' provide
examples of SMOBs. There are a maximum of 256 SMOBs.
File: scm.info, Node: Defining Ptobs, Next: Calling Scheme From C, Prev: Defining Smobs, Up: Operations
Defining Ptobs
--------------
"ptob"s are similar to smobs but define new types of port to which SCM
procedures can read or write. The following functions are defined in
the `ptobfuns':
typedef struct {
SCM (*mark)P((SCM ptr));
int (*free)P((FILE *p));
int (*print)P((SCM exp, SCM port, int writing));
SCM (*equalp)P((SCM, SCM));
int (*fputc)P((int c, FILE *p));
int (*fputs)P((char *s, FILE *p));
sizet (*fwrite)P((char *s, sizet siz, sizet num, FILE *p));
int (*fflush)P((FILE *stream));
int (*fgetc)P((FILE *p));
int (*fclose)P((FILE *p));
} ptobfuns;
The `.free' component to the structure takes a `FILE *' or other C
construct as its argument, unlike `.free' in a smob, which takes the
whole smob cell. Often, `.free' and `.fclose' can be the same
function. See `fptob' and `pipob' in `sys.c' for examples of how to
define ptobs.
File: scm.info, Node: Calling Scheme From C, Next: Continuations, Prev: Defining Ptobs, Up: Operations
Calling Scheme From C
---------------------
To use SCM as a whole from another program call `init_scm' or `run_scm'
as is done in `main()' in `scm.c'.
In order to call indivdual Scheme procedures from C code more is
required; SCM's storage system needs to be initialized. The simplest
way to do this for a statically linked single-thread program is to:
1. make a SCM procedure which calls your code's startup routine.
2. use the `#define RTL' flag when compiling `scm.c' to elide SCM's
`main()'.
3. In your `main()', call `run_scm' with arguments (`argc' and
`argv') to invoke your code's startup routine.
4. link your code with SCM at compile time.
For a dynamically linked single-thread program:
1. make an `init_' procedure for your code which will set up any
Scheme definitions you need and then call your startup routine
(*note Changing Scm::.).
2. Start SCM with command line arguments to dynamically link your
code. After your module is linked, the `init_' procedure will be
called, and hence your startup routine.
Now use `apply' (and perhaps `intern') to call Scheme procedures from
your C code. For example:
/* If this apply fails, SCM will catch the error */
apply(CDR(intern("srv:startup",sizeof("srv:startup")-1)),
mksproc(srvproc),
listofnull);
func = CDR(intern(rpcname,strlen(rpcname)));
retval = apply(func, cons(mksproc(srvproc), args), EOL);
SCM now has routines to make calling back to Scheme procedures easier:
- Function: int scm_ldfile (char *FILE)
Loads the Scheme source file FILE. Returns 0 if successful, non-0
if not. This function is used to load SCM's initialization file
`Init.scm'.
- Function: int scm_ldprog (char *FILE)
Loads the Scheme source file `(in-vicinity (program-vicinity)
FILE)'. Returns 0 if successful, non-0 if not.
This function is useful for compiled code init_ functions to load
non-compiled Scheme (source) files. `program-vicinity' is the
directory from which the calling code was loaded (*note Vicinity:
(slib)Vicinity.).
- Function: SCM scm_evstr (char *STR)
Returns the result of reading an expression from STR and
evaluating it.
- Function: void scm_ldstr (char *STR)
Reads and evaluates all the expressions from STR.
If you wish to catch errors during execution of Scheme code, then you
can use a wrapper like this for your Scheme procedures:
(define (srv:protect proc)
(lambda args
(define result #f) ; put default value here
(call-with-current-continuation
(lambda (cont)
(dynamic-wind (lambda () #t)
(lambda ()
(set! result (apply proc args))
(set! cont #f))
(lambda ()
(if cont (cont #f))))))
result))
Calls to procedures so wrapped will return even if an error occurs.
File: scm.info, Node: Continuations, Next: Evaluation, Prev: Calling Scheme From C, Up: Operations
Continuations
-------------
The scm procedure call-with-current-continuation calls it's argument
with an object of type `contin'.
If `CHEAP_CONTINUATIONS' is #defined (in `scmfig.h') the contin just
contains a jmp_buf. When the contin is applied, a longjmp of the
jmp_buf is done.
If `CHEAP_CONTINUATIONS' is not #defined the contin contains the
jmp_buf and a copy of the C stack between the call_cc stack frame and
BASE(rootcont). When the contin is applied:
* the stack is grown larger than the saved stack, if neccessary.
* the saved stack is copied back into it's original position.
* longjmp of the jmp_buf is called.
On systems with nonlinear stack disciplines (multiple stacks or
non-contiguous stack frames) copying the stack will not work properly.
These systems need to #define `CHEAP_CONTINUATIONS' in `scmfig.h'.